# -*- coding: utf-8 -*-

'''
Copyright (C) 2011 Daniele Simonetti

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'''

import sys, locale, string, socket, time, re, os
### PySide ###
import PySide
from threading import Thread
### UI ###
from watchlist_ui import *
### CONTENT PROVIDERS ###
import providers

from itemdelegates.wldelegate import *

from myepes_rc import *

### DATE TIME ###
from datetime import timedelta, datetime, date

SHOW_STATUS_ON    = 0x01
SHOW_STATUS_NEW   = 0x02
SHOW_STATUS_END   = 0x04


########## WATCHLIST CLASS ############
class Watchlist(QtGui.QWidget, Ui_Watchlist):
  
  # Define signals
  searchSerie   = QtCore.Signal(unicode)
  needSerieInfo = QtCore.Signal(str)
  removedSerie  = QtCore.Signal(str)
  rageSerie     = QtCore.Signal(str)
    
  def __init__(self, parent=None):
    super(Watchlist, self).__init__(parent)
    self.setupUi(self)
    self.model = WatchlistModel(self)
    self.tbvSeries.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch);
    QtCore.QObject.connect(self.leSearch, QtCore.SIGNAL("returnPressed()"), self.searchClicked)    
    
    self.setStyleSheet('''
QComboBox::drop-down { 
	margin: 7px;
    subcontrol-origin: margin;
}''')    
    self.setupActions()
    self.setupLegenda()
    
    # BIG FONT
    big_font = QtGui.QFont(self.font().family(), 16)
    self.cbFound.setFont(big_font)
    self.leSearch.setFont(big_font)
    
    # MEDIUM FONT
    med_font = QtGui.QFont(self.font().family(), 11)
    self.tbvSeries.setFont(med_font)
    self.pbAddSerie.setFont(med_font)        
    
  def event(self, e):
    if e.type() == providers.showsEventType:
      self.foundSeries(e.shows)
      return True
    elif e.type() == providers.epsEventType:
      self.foundEpisodes(e.source['showid'], e.eps)    
    return super(Watchlist, self).event(e)
  
  def setupLegenda(self):
    self.lbCol1.setStyleSheet('QLabel { background: rgb(%d,%d,%d); }' % (0x63, 0xff, 0x75) )
    self.lbCol2.setStyleSheet('QLabel { background: rgb(%d,%d,%d); }' % (0xe0, 0xe0, 0xe0) )
    self.lbCol1Tx.setText('Show is ongoing')
    self.lbCol2Tx.setText('Show is completed')
    self.lbEmblem1.setStyleSheet('QLabel { image: url(%s); }' % (':/icons/label_new_red.png') )
    self.lbEmblem1Tx.setText('New episodes available')
  
  def setupModel(self):
    self.tbvSeries.setModel(self.model)
    self.tbvSeries.setItemDelegateForColumn(2, WlItemDelegate(self))
    
  def setupActions(self):
    self.cx_info = QtGui.QAction('Info about this show', self)
    self.cx_rage = QtGui.QAction('Open in TvRAGE', self)
    self.cx_web = QtGui.QAction('Search the web', self)
    self.cx_rem = QtGui.QAction('Remove from Watchlist', self)
    
    cx_sep = QtGui.QAction(self)
    cx_sep.setSeparator(True)
    
    self.tbvSeries.addActions([ self.cx_info, self.cx_rage, self.cx_web, cx_sep, self.cx_rem ])
    
    self.cx_info.triggered.connect(self.triggerShowInfo)
    self.cx_rage.triggered.connect(self.triggerShowRage)
    self.cx_web .triggered.connect(self.triggerShowWeb )
    self.cx_rem .triggered.connect(self.removeShow     )
  
  def searchClicked(self):
    ''' slot for search button '''
    QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) 
    self.cbFound.setEnabled(False)
    self.searchSerie.emit(self.leSearch.text())
    #self.emit(QtCore.SIGNAL('searchSerie(QString)'), self.leSearch.text())

  def addSerieClicked(self):
    ''' slot for search button '''
    idx = self.cbFound.currentIndex()
    data = self.cbFound.itemData(idx)
    if data is not None:
        if self.model.watch_new_serie(data, self.cbFound.currentText()) :
            self.needSerieInfo.emit(data)            
        
  def foundSeries(self, series):
    self.cbFound.clear()
    for serie in series:
        self.cbFound.addItem(unicode(serie))
        self.cbFound.setItemData(self.cbFound.count()-1, serie.showid)
    self.cbFound.setEnabled(True)
    QtGui.QApplication.restoreOverrideCursor()
  
  def foundEpisodes(self, id, eps ):
    #print 'foundEpisodes of serie id: %s ' % id
    self.model.updateEpisodes(id, eps)
    self.tbvSeries.update()
   
  def get_items(self):
    return self.model.items
    
  def add_batch_items(self, items):
    for item in items:
        if self.model.watch_new_serie(item[0], item[1], item[2]) :
            self.needSerieInfo.emit(item[0])

  def removeShow(self):
    index = self.tbvSeries.selectionModel().currentIndex()
    if index.isValid():
        showid = self.model.key_at(index)
        self.model.remove_at(index)
        self.removedSerie.emit(showid)
   
  def triggerShowInfo(self):
    pass
  
  def triggerShowRage(self):
    index = self.tbvSeries.selectionModel().currentIndex()
    if index.isValid():
        showid = self.model.key_at(index)
        self.rageSerie.emit(showid)
  
  def triggerShowWeb(self):
    pass
   
########## WATCHLIST MODEL CLASS ############
class WatchlistModel(QtCore.QAbstractTableModel):
  def __init__(self, parent=None):
    super(WatchlistModel, self).__init__(parent)        
    self.wp = parent
    self.items = []
    self.imap = {}
    self.colmap = ['showid', 'title', 'lastep' ]
    self.header = [ (QtCore.Qt.Horizontal, "Show ID"),
                    (QtCore.Qt.Horizontal, "Serie name"),
                    (QtCore.Qt.Horizontal, "Last episode watched")]
                    
    self.status_colors = { SHOW_STATUS_ON: QtGui.QBrush(QtGui.QColor(0x63, 0xff, 0x75)),
                           SHOW_STATUS_END: QtGui.QBrush(QtGui.QColor(0xe0, 0xe0, 0xe0)) }
    self.text_color = QtGui.QBrush(QtGui.QColor(0x15, 0x15, 0x15))
  
  def rowCount(self, parent = QtCore.QModelIndex()):
    return len(self.items)
  
  def columnCount(self, parent = QtCore.QModelIndex()):
    return len(self.header)
  
  def key_at(self, index):
    return self.data(index, QtCore.Qt.UserRole)
   
  def remove_at(self, index):
    row = index.row()
    self.beginRemoveRows(QtCore.QModelIndex(), row, row)
    id = self.data(index, QtCore.Qt.UserRole)
    itm = self.imap.pop(id)
    # also remove from list... however this list should be removed
    self.items.remove(itm)
    self.endRemoveRows()
    
  def data(self, index, role):
    item = self.items[index.row()]
    if role == QtCore.Qt.DisplayRole:
        if index.column() == 2:
            lastep = item['lastep']
            if len(item['eps']) > lastep:
                return unicode(item['eps'][ lastep ])
            return 'Loading...'
        else:
            colnm = self.colmap[index.column()]
            return item[colnm]
    elif role == QtCore.Qt.DecorationRole:
        if index.column() == 0 and (item['epstatus'] & SHOW_STATUS_NEW == SHOW_STATUS_NEW):
            return QtGui.QIcon(':/icons/label_new_red.png')
    elif role == QtCore.Qt.BackgroundRole:
        s = item['epstatus']
        if s & SHOW_STATUS_END == SHOW_STATUS_END:
            return self.status_colors[ SHOW_STATUS_END ]
        elif s & SHOW_STATUS_ON == SHOW_STATUS_ON:
            return self.status_colors[ SHOW_STATUS_ON ]
    elif role == QtCore.Qt.UserRole:
        return item['showid']
    elif role == QtCore.Qt.ForegroundRole:
        return self.text_color
    
  def headerData(self, section, orientation, role):
    if orientation == QtCore.Qt.Horizontal:    
        return 'prova'
        #return self.header[section][1]
    #try:
    #    head = self.header[section]
    #    if orientation == head[0] and role == QtCore.Qt.DisplayRole:
    #        return head[1]
    #except:
    #    head = []
    #    print 'section not handled: %d' % (section)
    
    return None
    
    
  def watch_new_serie(self, showid, title, lastep = 0):
    if showid in self.imap:
        return False
  
    witem = {}
    witem['title'] = title
    witem['epstatus'] = SHOW_STATUS_ON
    witem['eps'] = []
    witem['lastep'] = lastep
    witem['showid'] = showid
    
    self.imap[showid] = witem
    self.append_item(witem)
    return True
    
  def append_item(self, item):
    row = self.rowCount()
    self.beginInsertRows(QtCore.QModelIndex(), row, row)
    self.items.append(item)
    for i in range(0, self.columnCount()):
        index = self.index(row, i)
        value = self.items[row][self.colmap[i]]
    self.endInsertRows()
    #self.emit(QtCore.SIGNAL('dataChanged()'))
    
  def flags(self, index):
    if not index.isValid():
        return QtCore.Qt.NoItemFlags
    flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable
    if index.column() == 0:
        flags = flags | QtCore.Qt.ItemIsUserCheckable
    elif index.column() == 2:
        item = self.items[index.row()]
        if len(item['eps']) > 1:
            flags = flags | QtCore.Qt.ItemIsEditable
    return flags
  
  def updateEpisodes(self, id, eps):
    ''' Updates episode data for the given showid '''
    if id in self.imap:
        self.imap[id]['eps'] = eps
        self.updateStatus(id)

  def updateStatus(self, id):
    eps = self.imap[id]['eps']
    last_see_ep = eps[ self.imap[id]['lastep'] ]
    last_aired_ep = None
    last_announced_ep = eps[ len(eps) - 1 ]
    today = date.today()
    try:            
        last_announced_airdate = datetime.strptime(last_announced_ep.airdate, '%Y-%m-%d').date()
    except:
        last_announced_airdate = date.min
        print 'invalid date format %s' % (last_announced_ep.airdate) 
    
    ep_dt = date.max
    i = len(eps)-1
    while ep_dt > today and i >= 0:
        last_aired_ep = eps[i]
        try:            
            dt = eps[i].airdate[0:10]
            ep_dt = datetime.strptime(dt, '%Y-%m-%d').date()
        except:
            ep_dt = date.min
            print 'invalid date format %s' % (eps[i].airdate[0:10])
        i = i - 1

    #print 'show: %s' %  (id)
    #print 'last see ep: %s' % ( unicode(last_see_ep) )            
    #print 'last aired ep: %s -> %s' % ( unicode(last_aired_ep), last_aired_ep.airdate )
    #print 'last announced ep: %s' % ( unicode(last_announced_ep) )    
    
    s = 0
    
    if last_announced_airdate < today:
        s = s | SHOW_STATUS_END        
    else:
        s = s | SHOW_STATUS_ON
    
    if int(last_see_ep.ep) < int(last_aired_ep.ep):
        s = s | SHOW_STATUS_NEW
        
    #print 'epstatus: %d' % (s)
    self.imap[id]['epstatus'] = s
    self.emit(QtCore.SIGNAL('dataChanged(QModelIndex, QModelIndex)'), 
    self.index(0,0), self.index(len(self.items)-1,0))
  
    
